package com.ssy.lingxi.order.serviceimpl.base;

import cn.hutool.core.collection.CollUtil;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.entity.OrderDeductionDO;
import com.ssy.lingxi.order.model.bo.VendorBO;
import com.ssy.lingxi.order.model.dto.OrderSeparateDTO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderDeductionVO;
import com.ssy.lingxi.order.repository.OrderDeductionRepository;
import com.ssy.lingxi.order.service.base.IBaseOrderDeductionService;
import com.ssy.lingxi.order.service.feign.IMemberFeignService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单积分抵扣相关接口实现类
 * @author wyx
 * @version 2.0.0
 * @date 2022-03-02
 **/
@Service
public class BaseOrderDeductionServiceImpl implements IBaseOrderDeductionService {
    @Resource
    private OrderDeductionRepository orderDeductionRepository;
    @Resource
    private IMemberFeignService memberFeignService;


    /**
     * 校验、保存订单关联的积分抵扣列表
     * @param order      订单
     * @param deductions 积分抵扣列表
     * @return 保存结果
     */
    @Override
    public Wrapper<Void> checkOrderDeduction(OrderDO order, List<OrderDeductionVO> deductions, Map<VendorBO, BigDecimal> pointsMap) {
        if (CollUtil.isEmpty(deductions)) {
            return Wrapper.success();
        }

        //校验平台通用积分和供应会员积分是否同时使用，只能选一
        boolean isSame = deductions.stream().allMatch(d -> d.getRelType().equals(deductions.get(0).getRelType()));
        if (!isSame) {
            return Wrapper.fail(ResponseCode.ORDER_PLATFORM_MEMBER_POINTS_NOT_USE_TOGETHER);
        }

        //判断是否为平台积分
        boolean isPlatform = MemberRelationTypeEnum.PLATFORM.getCode().equals(deductions.get(0).getRelType());
        BigDecimal points;
        List<OrderDeductionVO> orderDeductionList = new ArrayList<>();
        if (isPlatform) {//平台积分
            points = pointsMap.getOrDefault(new VendorBO(1L, 1L), BigDecimal.ZERO);
            orderDeductionList.addAll(deductions);
        } else {//店铺积分
            points = pointsMap.getOrDefault(new VendorBO(order.getVendorMemberId(), order.getVendorRoleId()), BigDecimal.ZERO);
            orderDeductionList.addAll(deductions.stream().filter(d -> d.getVendorMemberId().equals(order.getVendorMemberId()) && d.getVendorRoleId().equals(order.getVendorRoleId())).collect(Collectors.toList()));
        }

        //可用积分
        BigDecimal usePoints = order.getDeductionAmount().multiply(points).setScale(0, BigDecimal.ROUND_HALF_UP);

        //调用会员服务校验可用积分、扣减积分
        Wrapper<Void> deductionResult = memberFeignService.memberDeductionPoints(order, orderDeductionList, usePoints);
        if (deductionResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return deductionResult;
        }

        Set<OrderDeductionDO> orderDeductions = orderDeductionList.stream().map(d -> {
            OrderDeductionDO deduction = new OrderDeductionDO();
            deduction.setOrder(order);
            deduction.setVendorMemberId(d.getVendorMemberId());
            deduction.setVendorRoleId(d.getVendorRoleId());
            deduction.setVendorName(d.getVendorName());
            deduction.setType(d.getRelType());
            deduction.setUsedPoint(usePoints.intValue());
            deduction.setAmount(order.getDeductionAmount());
            return deduction;
        }).collect(Collectors.toSet());

        orderDeductionRepository.saveAll(orderDeductions);
        return Wrapper.success();
    }

    /**
     * 订单取消，返还已抵扣的积分
     * @param order 订单
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> returnDeductionPoints(OrderDO order) {
        if (NumberUtil.isNullOrNegativeZero(order.getDeductionAmount())) {
            return Wrapper.success();
        }
        return memberFeignService.returnDeductionPoints(order);
    }

    /**
     * （拆单）根据拆单订单商品金额总和，加权平均计算拆单后的积分抵扣金额
     * @param separateSkuMap 拆单商品Sku列表
     * @param skuCouponMap   Sku积分抵扣减少的金额
     * @return 拆单订单优惠券金额
     */
    @Override
    public Map<OrderSeparateDTO, BigDecimal> findSeparateOrderDeductionAmount(Map<OrderSeparateDTO, List<Long>> separateSkuMap, Map<Long, BigDecimal> skuCouponMap) {
        return separateSkuMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, skuIds -> skuCouponMap.entrySet().stream().filter(entry -> skuIds.getValue().contains(entry.getKey())).map(Map.Entry::getValue).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP)));
    }

    /**
     * 供应商积分抵扣比例
     * @param deductions 积分抵扣列表
     * @return 积分抵扣比例
     */
    @Override
    public Map<VendorBO, BigDecimal> vendorCalculateDeductionPoints(List<OrderDeductionVO> deductions) {
        if (CollUtil.isEmpty(deductions)) {
            return new HashMap<>();
        }
        return deductions.stream().collect(Collectors.toMap(v -> new VendorBO(v.getVendorMemberId(), v.getVendorRoleId()), OrderDeductionVO::getDeductionRate));
    }
}
